﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace PTA.Image
{
    /// <summary>
    /// 图片缩放处理类
    /// </summary>
    public static class ImageUtils
    {
        /// <summary>
        /// 根据参数提供的条件，缩放图片
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的保存路径</param>
        /// <param name="setting">缩放配置</param>
        public static void Zoom(string ori, string dest, ImageZoomSetting setting)
        {
            Zoom(ori, dest, setting.OriX, setting.OriY, setting.OriWidth, setting.OriHeight, setting.Width, setting.Height, setting.Zoom, setting.BgColor,
                setting.Format, setting.InnerBorderWidth, setting.InnerBorderColor, setting.OuterBorderWidth, setting.OuterBorderColor);
        }

        /// <summary>
        /// 根据参数提供的条件，缩放图片.
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的保存路径</param>
        /// <param name="orix">原始图片的X起始位置</param>
        /// <param name="oriy">原始图片的Y起始位置</param>
        /// <param name="oriheight">原始图片的X长度,如果大于图片的长度或者为0,则使用图片的长度</param>
        /// <param name="oriwidth">原始图片的Y长度,如果大于图片的高度或者为0,则使用图片的高度</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        /// <param name="zoom">缩放类型</param>
        /// <param name="backColor">图片填充的背景色</param>
        /// <param name="format">图片类型</param>
        /// <param name="innerWidth">图片内边框宽度</param>
        /// <param name="innerColor">图片内边框颜色</param>
        /// <param name="outerWidth">图片外边框宽度</param>
        /// <param name="outerColor">图片外边框颜色</param>
        public static void Zoom(string ori, string dest, int orix, int oriy, int oriwidth, int oriheight, int width, int height, ZoomType zoom, Color backColor,
            ImageFormat format, int innerWidth, Color innerColor, int outerWidth, Color outerColor)
        {
            if (!string.IsNullOrEmpty(ori) && System.IO.File.Exists(ori))
            {
                int imgWidth = width - 2 * innerWidth - 2 * outerWidth;
                int imgHeight = height - 2 * innerWidth - 2 * outerWidth;
                if (imgWidth > 0 && imgHeight > 0)
                {
                    using (System.Drawing.Image oriImage = System.Drawing.Image.FromFile(ori))
                    {
                        if (oriwidth == 0 || oriwidth > oriImage.Width - orix)
                        {
                            oriwidth = oriImage.Width - orix;
                        }
                        if (oriheight == 0 || oriheight > oriImage.Height - oriy)
                        {
                            oriheight = oriImage.Height - oriy;
                        }
                        switch (zoom)
                        {
                            case ZoomType.参照X等比例缩放画布:
                                {
                                    height = (int)((double)width * (double)oriImage.Height / (double)oriImage.Width);
                                    imgHeight = height - 2 * innerWidth - 2 * outerWidth;
                                    imgWidth = width - 2 * innerWidth - 2 * outerWidth;
                                    break;
                                }
                            case ZoomType.参照Y等比例缩放画布:
                                {
                                    width = (int)((double)height * (double)oriImage.Width / (double)oriImage.Height);
                                    imgWidth = width - 2 * innerWidth - 2 * outerWidth;
                                    imgHeight = height - 2 * innerWidth - 2 * outerWidth;
                                    break;
                                }
                            case ZoomType.参照X等比例缩放图片:
                                {
                                    imgHeight = (int)((double)width * (double)oriImage.Height / (double)oriImage.Width);
                                    imgWidth = width - 2 * innerWidth - 2 * outerWidth;
                                    break;
                                }
                            case ZoomType.参照Y等比例缩放图片:
                                {
                                    imgWidth = (int)((double)height * (double)oriImage.Width / (double)oriImage.Height);
                                    imgHeight = height - 2 * innerWidth - 2 * outerWidth;
                                    break;
                                }
                            case ZoomType.智能缩放:
                                {
                                    if ((double)width / (double)oriwidth > (double)height / (double)oriheight)
                                    {
                                        goto case ZoomType.参照Y等比例缩放图片;
                                    }
                                    else
                                    {
                                        goto case ZoomType.参照X等比例缩放图片;
                                    }
                                }

                        }
                        using (System.Drawing.Image destImg = new System.Drawing.Bitmap(width, height))
                        {
                            System.Drawing.Graphics g = CreateGraphics(destImg, backColor);

                            DrawImage(oriImage, orix, oriy, oriwidth, oriheight, g, (width - imgWidth) / 2, (height - imgHeight) / 2, imgWidth, imgHeight);
                            if (outerWidth > 0)
                            {
                                g.DrawRectangle(new Pen(outerColor, outerWidth), outerWidth / 2, outerWidth / 2, width - outerWidth, height - outerWidth);
                            }
                            if (innerWidth > 0)
                            {
                                g.DrawRectangle(new Pen(innerColor, innerWidth), outerWidth + innerWidth / 2, outerWidth + innerWidth / 2, width - 2 * outerWidth - innerWidth, height - 2 * outerWidth - innerWidth);
                            }
                            destImg.Save(dest, format);
                        }
                    }
                }
                else
                {
                    throw new Exception("给定的参数无法生成图片,图片的宽度或高度太小");
                }
            }
            else
            {
                throw new Exception("未找到原始的图片信息,无法进行缩放");
            }
        }

        /// <summary>
        /// 根据参数提供的条件，缩放图片.
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的缓存路径</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        /// <param name="zoom">缩放类型</param>
        /// <param name="backColor">图片填充的背景色</param>
        /// <param name="format">图片类型</param>
        /// <param name="innerWidth">图片内边框宽度</param>
        /// <param name="innerColor">图片内边框颜色</param>
        /// <param name="outerWidth">图片外边框宽度</param>
        /// <param name="outerColor">图片外边框颜色</param>
        public static void Zoom(string ori, string dest, int width, int height, ZoomType zoom, Color backColor, ImageFormat format, int innerWidth, Color innerColor, int outerWidth, Color outerColor)
        {
            Zoom(ori, dest, 0, 0, int.MaxValue, int.MaxValue, width, height, zoom, backColor, format, innerWidth, innerColor, outerWidth, outerColor);
        }

        /// <summary>
        /// 根据参数提供的条件，缩放图片
        /// <para>
        ///     <para>没有边框</para>
        ///     <para>保存为JPEG格式</para>
        ///     <para>按照给定的比例缩放</para>
        ///     <para>背景使用透明色</para>
        /// </para>
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的缓存路径</param>
        /// <param name="orix">原始图片的X起始位置</param>
        /// <param name="oriy">原始图片的Y起始位置</param>
        /// <param name="oriheight">原始图片的X长度,如果大于图片的长度或者为0,则使用图片的长度</param>
        /// <param name="oriwidth">原始图片的Y长度,如果大于图片的高度或者为0,则使用图片的高度</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        /// <param name="zoom">缩放类型</param>
        public static void Zoom(string ori, string dest, int orix, int oriy, int oriwidth, int oriheight, int width, int height, ZoomType zoom)
        {
            Zoom(ori, dest, orix, oriy, oriwidth, oriheight, width, height, zoom, Color.Transparent, ImageFormat.Jpeg, 0, Color.White, 0, Color.White);
        }

        /// <summary>
        /// 根据参数提供的条件，缩放图片
        /// <para>
        ///     <para>没有边框</para>
        ///     <para>保存为JPEG格式</para>
        ///     <para>按照给定的比例缩放</para>
        ///     <para>背景使用透明色</para>
        /// </para>
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的缓存路径</param>
        /// <param name="orix">原始图片的X起始位置</param>
        /// <param name="oriy">原始图片的Y起始位置</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        /// <param name="zoom">缩放类型</param>
        public static void Zoom(string ori, string dest, int orix, int oriy, int width, int height, ZoomType zoom)
        {
            Zoom(ori, dest, orix, oriy, int.MaxValue, int.MaxValue, width, height, zoom, Color.Transparent, ImageFormat.Jpeg, 0, Color.White, 0, Color.White);
        }

        /// <summary>
        /// 根据参数提供的条件，缩放图片
        /// <para>
        ///     <para>没有边框</para>
        ///     <para>保存为JPEG格式</para>
        ///     <para>按照给定的比例缩放</para>
        ///     <para>背景使用透明色</para>
        /// </para>
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的缓存路径</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        /// <param name="zoom">缩放类型</param>
        public static void Zoom(string ori, string dest, int width, int height, ZoomType zoom)
        {
            Zoom(ori, dest, 0, 0, int.MaxValue, int.MaxValue, width, height, zoom, Color.Transparent, ImageFormat.Jpeg, 0, Color.White, 0, Color.White);
        }

        /// <summary>
        /// 使用默认的参数缩放图片
        /// <para>
        ///     <para>没有边框</para>
        ///     <para>保存为JPEG格式</para>
        ///     <para>按照给定的比例缩放</para>
        /// </para>
        /// </summary>
        /// <param name="ori">图片的原始路径</param>
        /// <param name="dest">图片的缓存路径</param>
        /// <param name="width">图片的宽度</param>
        /// <param name="height">图片的高度</param>
        public static void Zoom(string ori, string dest, int width, int height)
        {
            Zoom(ori, dest, width, height, ZoomType.按照给定的比例缩放);
        }

        /// <summary>
        /// 创建默认的画笔
        /// </summary>
        /// <param name="fromImage">画笔对应的图片</param>
        /// <param name="backColor">画笔背景色</param>
        /// <returns></returns>
        private static System.Drawing.Graphics CreateGraphics(System.Drawing.Image fromImage, Color backColor)
        {
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(fromImage);//新建一个画笔
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;//设置高质量插值法
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;//设置高质量,低速度呈现平滑程度
            g.Clear(backColor);//清空画布并以透明背景色填充
            return g;
        }

        /// <summary>
        /// 利用画笔画图
        /// </summary>
        /// <param name="oriImage"></param>
        /// <param name="orix"></param>
        /// <param name="oriy"></param>
        /// <param name="oriwidth"></param>
        /// <param name="oriheight"></param>
        /// <param name="g"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        private static void DrawImage(System.Drawing.Image oriImage, int orix, int oriy, int oriwidth, int oriheight, Graphics g, int x, int y, int width, int height)
        {
            g.DrawImage(oriImage, new Rectangle(x, y, width, height), new Rectangle(orix, oriy, oriwidth, oriheight), GraphicsUnit.Pixel);
        }

        /// <summary>
        /// 根据参数提供的字符串生成图片，如生成验证码
        /// </summary>
        /// <param name="width">图片宽度</param>
        /// <param name="height">图片高度</param>
        /// <param name="input">要生成的图片包含的文字</param>
        /// <param name="lineCount">干扰线的数量</param>
        /// <param name="pointCount">干扰点的数量</param>
        /// <param name="rotete">是否旋转</param>
        /// <returns>生成的图片的二进制数据流</returns>
        public static System.IO.MemoryStream DrawTextImage(int width, int height, string input, int lineCount, int pointCount, bool rotete)
        {
            input = input ?? string.Empty;
            Bitmap img = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            Graphics g = CreateGraphics(img, Color.White);
            Random rand = new Random();
            LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, width, height), Color.Red, Color.Blue, 1.2f, true);
            int top = (height - 14) / 2;
            if (rotete)
            {
                for (int i = 0; i < input.Length; i++)
                {
                    g.RotateTransform((float)rand.Next(-1, 1));
                    g.DrawString(input[i].ToString(), new Font("Courier New", (float)rand.Next(11, 14), FontStyle.Italic | FontStyle.Bold), brush, 1 + i * 14, top);
                }
            }
            else
            {
                g.DrawString(input, new Font("Courier New", (float)rand.Next(11, 14), FontStyle.Italic | FontStyle.Bold), brush, 2, top);
            }
            g.DrawRectangle(new Pen(Color.Silver), 0, 0, width - 1, height - 1);

            #region 画点 画线
            Random r = new Random();
            for (int i = 0; i < lineCount; i++)
            {
                int x1 = r.Next(img.Width);
                int x2 = r.Next(img.Width);
                int y1 = r.Next(img.Height);
                int y2 = r.Next(img.Height);
                g.DrawLine(new Pen(Color.FromArgb(r.Next())), x1, y1, x2, y2);
            }
            //绘图画面点数干扰
            for (int i = 0; i < pointCount; i++)
            {
                int x = r.Next(img.Width);
                int y = r.Next(img.Height);
                img.SetPixel(x, y, Color.FromArgb(r.Next()));
            }
            #endregion

            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            img.Save(ms, ImageFormat.Gif);
            return ms;
        }
    }

    /// <summary>
    /// 设置缩放的类型
    /// </summary>
    public enum ZoomType
    {
        /// <summary>
        /// 不对图片进行缩放
        /// </summary>
        不缩放 = 0,

        /// <summary>
        /// 按照给定的比例在XY方向缩放
        /// </summary>
        按照给定的比例缩放 = 1,

        /// <summary>
        ///  按照给定的X值等比例缩放画布
        /// <para>
        /// 图片缩放完成之后,图片的宽度为指定的宽度,而图片的高度会根据要缩放的图片的比例进行计算得到. 
        /// </para>
        /// <para>
        /// 进行这种缩放,图片不会产生填充色.
        /// </para>
        /// </summary>
        参照X等比例缩放画布 = 2,

        /// <summary>
        /// 按照给定的X值等比例缩放图片
        /// </summary>
        /// <para>
        /// 进行这种缩放,图片的大小为指定的值,但因为是按照X的比例计算Y的高度.所以在缩放完成后,
        /// 在Y的方向上会出现裁切或填充背景色 
        /// </para>
        参照X等比例缩放图片 = 3,

        /// <summary>
        /// 按照给定的Y值等比例缩放画布
        /// <para>
        ///  图片缩放完成之后,图片的高度为指定的高度,而图片的宽度会根据要缩放的图片的比例进行计算得到. 
        /// </para>
        /// <para>
        /// 进行这种缩放,图片不会产生填充色.
        /// </para>
        /// </summary>
        参照Y等比例缩放画布 = 4,

        /// <summary>
        /// 按照给定的Y值等比例缩放图片 
        /// <para>
        /// 进行这种缩放,图片的大小为指定的值,但因为是按照Y的比例计算Y的高度.所以在缩放完成后,
        /// 在X的方向上会出现裁切或填充背景色 
        /// </para>
        /// </summary>
        参照Y等比例缩放图片 = 5,

        /// <summary>
        /// 在保持等比例的前提下,由程序决定是按照X还是Y等比例缩放图片.
        /// </summary>
        智能缩放 = 9
    }
}
